import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:ichineseaplus/domain/core/constants/request_header.constants.dart';
import 'package:ichineseaplus/domain/core/constants/storage.constants.dart';
import 'package:ichineseaplus/domain/core/utils/snackbar.util.dart';
import 'package:ichineseaplus/generated/locales.g.dart';
import 'package:ichineseaplus/infrastructure/navigation/bindings/domains/auth.repository.binding.dart';
import 'package:ichineseaplus/infrastructure/navigation/routes.dart';
import 'package:ichineseaplus/presentation/shared/loading/loading.controller.dart';
import 'package:logger/logger.dart';
import 'package:url_strategy/url_strategy.dart';

import 'config.dart';

class Initializer {
  static Future<void> init() async {
    try {
      WidgetsFlutterBinding.ensureInitialized();
      await _initStorage();
      await _initGetConnect();
      _initGlobalLoading();
      setPathUrlStrategy();
    } catch (err) {
      rethrow;
    }
  }

  static Future<void> _initGetConnect() async {
    final connect = GetConnect();
    final url = ConfigEnvironments.getApiConstants().baseAPI;
    connect.baseUrl = url;
    connect.timeout = const Duration(seconds: 12);
    connect.httpClient.maxAuthRetries = 2;

    connect.httpClient.addRequestModifier<dynamic>(
      (request) {
        final storage = Get.find<GetStorage>();
        final token = storage.read<String>(StorageConstants.tokenAuthorization);
        if (token != null) {
          request.headers[RequestHeaderConstants.authTokenRequestHeader] =
              token;
        }
        return request;
      },
    );

    connect.httpClient.addResponseModifier(
      (request, response) async {
        if (response.statusCode == 401) {
          final authDomainBinding = AuthRepositoryBinding();
          await authDomainBinding.repository.logoutUser();
          Get.offAllNamed([Routes.ICA, Routes.LOGIN].join());
          SnackbarUtil.showWarning(
            message: LocaleKeys.initializer_unauthorizedAccess.tr,
         );
        }
        if (response.statusCode == 403) {
          final authDomainBinding = AuthRepositoryBinding();
          await authDomainBinding.repository.logoutUser();
          Get.offAllNamed([Routes.ICA, Routes.LOGIN].join());
          SnackbarUtil.showWarning(
            message: LocaleKeys.initializer_dueToInactivity.tr,
         );
        }

        return response;
      },
    );

    connect.httpClient.addAuthenticator<dynamic>(
      (request) async {
        final token =
            await Get.toNamed<String>([Routes.ICA, Routes.LOGIN].join());
        if (token != null) {
          final storage = Get.find<GetStorage>();
          await storage.write(StorageConstants.tokenAuthorization, token);
          request.headers[RequestHeaderConstants.authTokenRequestHeader] =
              token;
        }
        return request;
      },
    );

    Logger().i('Connected in: $url');
    Get.put(connect);
  }

  static void _initGlobalLoading() {
    final loading = LoadingController();
    Get.put(loading);
  }

  static Future<void> _initStorage() async {
    await GetStorage.init();
    Get.put(GetStorage());
  }
}
